﻿using System;
using System.Collections.Generic;
using System.Text;

namespace DotNetCommon.Validate
{
    /// <summary>
    /// 校验扩展
    /// </summary>
    public static class ValidateExtensions
    {
        /// <summary>
        /// 不能为空
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustNotNull<T>(this ValidateContext<T> ctx, string errorMessage = null)
        {
            if (ctx.Model == null) ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 不能为空!"));
            return ctx;
        }

        /// <summary>
        /// 必须为空
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustBeNull<T>(this ValidateContext<T> ctx, string errorMessage = null)
        {
            if (ctx.Model != null) ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须为空!"));
            return ctx;
        }

        #region 相等Object.Equals & 比较大小IComparable<T>
        /// <summary>
        /// 必须等于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustEqualTo<T>(this ValidateContext<T> ctx, T value, string errorMessage = null)
        {
            if ((ctx.Model == null && value == null) || ctx.Model.Equals(value)) { }
            else
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须等于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须等于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T?> MustEqualTo<T>(this ValidateContext<T?> ctx, T? value, string errorMessage = null) where T : struct
        {
            if ((ctx.Model == null && value == null) || ctx.Model.Equals(value)) { }
            else
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须等于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 不能等于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustNotEqualTo<T>(this ValidateContext<T> ctx, T value, string errorMessage = null)
        {
            if ((ctx.Model == null && value == null) || ctx.Model.Equals(value))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 不能等于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 不能等于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T?> MustNotEqualTo<T>(this ValidateContext<T?> ctx, T? value, string errorMessage = null) where T : struct
        {
            if ((ctx.Model == null && value == null) || ctx.Model.Equals(value))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 不能等于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须小于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustLessThan<T>(this ValidateContext<T> ctx, T value, string errorMessage = null)
        {
            if (ctx.Model == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value) >= 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须小于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须小于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T?> MustLessThan<T>(this ValidateContext<T?> ctx, T? value, string errorMessage = null) where T : struct
        {
            if (ctx.Model == null || value == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value.Value) >= 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须小于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须小于或等于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustLessThanOrEuqalTo<T>(this ValidateContext<T> ctx, T value, string errorMessage = null)
        {
            if (ctx.Model == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value) > 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须小于等于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须小于或等于value
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T?> MustLessThanOrEuqalTo<T>(this ValidateContext<T?> ctx, T? value, string errorMessage = null) where T : struct
        {
            if (ctx.Model == null || value == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value.Value) > 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须小于等于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须大于某个值
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustGreaterThan<T>(this ValidateContext<T> ctx, T value, string errorMessage = null)
        {
            if (ctx.Model == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value) <= 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须大于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须大于某个值
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T?> MustGreaterThan<T>(this ValidateContext<T?> ctx, T? value, string errorMessage = null) where T : struct
        {
            if (ctx.Model == null || value == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value.Value) <= 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须大于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须大于等于某个值
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T> MustGreaterThanOrEuqalTo<T>(this ValidateContext<T> ctx, T value, string errorMessage = null)
        {
            if (ctx.Model == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value) < 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须大于等于 '{value}'!"));
            }
            return ctx;
        }

        /// <summary>
        /// 必须大于等于某个值
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="value"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        public static ValidateContext<T?> MustGreaterThanOrEuqalTo<T>(this ValidateContext<T?> ctx, T? value, string errorMessage = null) where T : struct
        {
            if (ctx.Model == null || value == null || ((ctx.Model is IComparable<T> t) && t.CompareTo(value.Value) < 0))
            {
                ctx.ErrorMessage.Add((ctx.ModelPath, errorMessage ?? $"'{ctx.ModelPath}' 必须大于等于 '{value}'!"));
            }
            return ctx;
        }
        #endregion
    }
}
